package me.gall.web.common.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;

import org.springframework.orm.jpa.support.JpaDaoSupport;

public abstract class BasicDao<T, PK extends Serializable> extends JpaDaoSupport {

	public T persist(T t) {
		getJpaTemplate().persist(t);
		return t;
	}

	public T merge(T t) {
		return getJpaTemplate().merge(t);
	}

	public void remove(T t) {
		getJpaTemplate().remove(t);
	}

	public T refresh(T t) {
		getJpaTemplate().refresh(t);
		return t;
	}

	public T find(Class<T> clazz, PK id) {
		return preLazyLoadEntity(getJpaTemplate().find(clazz, id));
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll(Class<T> clazz) {
		List<T> list = getJpaTemplate().find("select t from " + clazz.getName() + " t");
		list.size();
		return preLazyLoadEntities(list);
	}

	@SuppressWarnings("unchecked")
	public List<T> find(String queryString) {
		List<T> list = getJpaTemplate().find(queryString);
		list.size();
		return preLazyLoadEntities(list);
	}

	@SuppressWarnings("unchecked")
	public List<T> findByNamedParams(String queryString, Map<String, ?> params) {
		List<T> list = getJpaTemplate().findByNamedParams(queryString, params);
		list.size();
		return preLazyLoadEntities(list);
	}

	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName) {
		List<T> list = getJpaTemplate().findByNamedQuery(queryName);
		list.size();
		return preLazyLoadEntities(list);
	}

	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName, Map<String, ?> params) {
		List<T> list = getJpaTemplate().findByNamedQueryAndNamedParams(queryName, params);
		list.size();
		return preLazyLoadEntities(list);
	}

	public T getReference(Class<T> clazz, PK id)
	{
		return getJpaTemplate().getReference(clazz, id);
	}

	public EntityManager getEntityManager()
	{
		return getJpaTemplate().getEntityManagerFactory().createEntityManager();
	}

	/**
	 * @param t
	 * The entity to be lazy load manually.
	 * @return
	 * The entity
	 */
	public abstract T preLazyLoadEntity(T t);

	/**
	 * @param list
	 * The entities list to be lazy load manually.
	 * @return
	 * The entities list
	 */
	public abstract List<T> preLazyLoadEntities(List<T> list);
}
